<template>
  <div class="tms-ag-grid" v-loading="loading">
    <!-- table表格 -->
    <ag-grid-vue :style="{ width: '100%', height: tableHeight + 'px' }" :class="{ 'ag-theme-balham': true, 'tms-ag-group': isGroup, 'tms-highlight-current-row': highlightCurrentRow }" ref="agGridVue"
      v-bind="$attrs" :animateRows="true" :gridOptions="gridOptions" :localeText="localeText" :columnDefs="columns" :rowData="rowData" :rowSelection="rowSelection" :rowDragManaged="rowDragManaged"
      :suppressRowClickSelection="hasCheck" :rowHeight="30" :headerHeight="tmsShowFilter ? 30 : 45" :floatingFiltersHeight="tmsShowFilter ? 45 : 0" :singleClickEdit="true"
      @cell-clicked="onCellClicked" @cell-double-clicked="onCellDoubleClicked" @row-clicked="onRowClicked" @cell-editing-stopped="onCellEditingStopped" @row-editing-stopped="onRowEditingStopped"
      @row-drag-end="onRowDragEnd" @row-double-clicked="onRowDoubleClicked" @row-selected="select" @selection-changed="selectionChange" @row-value-changed="currentChange"
      @sort-changed="sortChangeHandler" @filter-changed="filterChangeHandler" @grid-ready="onGridReady" @gridSizeChanged="tmsColumnsFit" @row-data-changed="tmsColumnsFit"
      @grid-columns-changed="tmsColumnsFit">
    </ag-grid-vue>
    <!-- 设置 -->
    <section class="table-setting" @click="tableSetting" v-show="tableSettingVisible" :style="{ left: hasIndex ? '80px' : '30px' }">
      <i class="el-icon-setting"></i>
    </section>
    <div v-if="searchBox == true" class="search_btn" :style="{ left: !hasCheck||!hasEdit ? '4px' : '54px' }">
      <i @click="getTableData" class="el-icon-search"></i>
      <i @click="delSearchData($event)" class="el-icon-delete"></i>
    </div>
    <!-- 分页 -->
    <div v-if="pageDetail" class="pagination-container page">
      <!-- <div class="pageCon" :style="{ border: pageDetail ? '1px solid #e0e6ed' : '0px' }">
        <template v-if="pageDetail">
          {{ $t('app.page', { page: pageNum, pageSize, total, num: Math.ceil(total / pageSize) })}}
        </template>
      </div> -->
      <div class="block">
        <el-pagination layout="total, sizes, prev, pager, next" background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageNum" :page-sizes="pageSizes"
          :page-size="pageSize" :total="total">
        </el-pagination>
      </div>
    </div>
    <div class="clearfix"></div>

    <!-- table设置弹窗 -->
    <el-dialog :title="$t('other.customtable')" v-dialogDrag :visible.sync="showTableSetting" width="900px" class="tms-setting-dialog" :close-on-click-modal="false" append-to-body>
      <el-tabs v-model="settingTab" v-if="showTableSetting">
        <el-tab-pane :label="$t('other.tableshowconfig')" name="first">
          <section class="left-table">
            <div class="setting-title">
              {{ $t('other.hidefield') }}（{{ hideColumns.length }}）
            </div>
            <el-table border fit highlight-current-row stripe :data="hideColumns" height="330px" @selection-change="leftSelectionChange">
              <el-table-column class-name="tms-index-column" align="center" fixed type="selection" width="50"></el-table-column>
              <el-table-column align="center" minWidth="150" prop="name" :label="$t('other.fieldname')" :show-overflow-tooltip="true"> </el-table-column>
              <el-table-column align="center" minWidth="100" prop="width" :label="$t('other.fieldwidth') + '(PX)'" :show-overflow-tooltip="true"> </el-table-column>
            </el-table>
          </section>
          <section class="middle-action">
            <section class="action-main">
              <el-button type="primary" plain icon="el-icon-arrow-right" circle @click="moveRight">
              </el-button>
              <el-button type="primary" plain icon="el-icon-arrow-left" circle @click="moveLeft"> </el-button>
            </section>
          </section>
          <section class="right-table right-table-setting ui-right-table">
            <div class="setting-title">
              {{ $t('other.showfield') }}（{{ showColumns.length }}）
            </div>
            <el-table border fit highlight-current-row stripe row-key="field" :data="showColumns" height="330px" @selection-change="rightSelectionChange">
              <el-table-column class-name="tms-index-column" align="center" type="selection" width="50">
              </el-table-column>
              <el-table-column minWidth="150" prop="name" :label="$t('other.fieldname')" :show-overflow-tooltip="true" align="center"> </el-table-column>
              <el-table-column class-name="width-edit-column" align="center" minWidth="100" prop="width" :label="$t('other.fieldwidth') + '(PX)'" :show-overflow-tooltip="true">
                <template slot-scope="scope">
                  <el-input v-model="scope.row.width"></el-input>
                </template>
              </el-table-column>
              <el-table-column align="center" class-name="drag-action-column" minWidth="70" prop="action" :label="$t('other.drag')">
                <template slot-scope="scope">
                  <i class="el-icon-rank"></i>
                  <span style="display:none;">{{ scope.rows }}</span>
                </template>
              </el-table-column>
            </el-table>
          </section>
        </el-tab-pane>
        <el-tab-pane :label="$t('other.tableexportconfig')" name="second">
          <section class="left-table">
            <div class="setting-title">
              {{ $t('other.hidefield') }}（{{ hideExportColumns.length }}）
            </div>
            <el-table border fit highlight-current-row stripe :data="hideExportColumns" height="330px" @selection-change="leftExportSelectionChange">
              <el-table-column class-name="tms-index-column" align="center" fixed type="selection" width="50"></el-table-column>
              <el-table-column align="center" minWidth="150" prop="name" :label="$t('other.fieldname')" :show-overflow-tooltip="true"> </el-table-column>
              <el-table-column align="center" minWidth="100" prop="width" :label="$t('other.fieldwidth') + '(PX)'" :show-overflow-tooltip="true"> </el-table-column>
            </el-table>
          </section>
          <section class="middle-action">
            <section class="action-main">
              <el-button type="primary" plain icon="el-icon-arrow-right" circle @click="moveExportRight"> </el-button>
              <el-button type="primary" plain icon="el-icon-arrow-left" circle @click="moveExportLeft"> </el-button>
            </section>
          </section>
          <section class="right-table right-export-table">
            <div class="setting-title">
              {{ $t('other.showfield') }}（{{ showExportColumns.length }}）
            </div>
            <el-table border fit highlight-current-row stripe row-key="field" :data="showExportColumns" height="330px" @selection-change="rightExportSelectionChange">
              <el-table-column class-name="tms-index-column" align="center" type="selection" width="50">
              </el-table-column>
              <el-table-column minWidth="150" prop="name" :label="$t('other.fieldname')" :show-overflow-tooltip="true" align="center"> </el-table-column>
              <el-table-column class-name="width-edit-column" align="center" minWidth="100" prop="width" :label="$t('other.fieldwidth') + '(PX)'" :show-overflow-tooltip="true">
                <template slot-scope="scope">
                  <el-input v-model="scope.row.width"></el-input>
                </template>
              </el-table-column>
              <el-table-column align="center" class-name="drag-action-column" minWidth="70" prop="action" :label="$t('other.drag')">
                <template slot-scope="scope">
                  <i class="el-icon-rank"></i>
                  <span style="display:none;">{{ scope.rows }}</span>
                </template>
              </el-table-column>
            </el-table>
          </section>
        </el-tab-pane>
      </el-tabs>
      <section slot="footer" class="dialog-footer">
        <el-button plain type="primary" @click="applySetting" :loading="tableSetLoading" :disabled="tableSetLoading">{{
          $t('other.apply')
        }} </el-button>
        <el-button plain @click="resetSetting" :loading="tableSetLoading" :disabled="tableSetLoading">{{
          $t('other.reset')
        }}</el-button>
        <el-button plain @click="showTableSetting = false">{{ $t('other.cancel') }}</el-button>
      </section>
    </el-dialog>
  </div>
</template>
<script>
import Sortable from 'sortablejs'
import { getColumnConfig } from '@/api/system/table'
import { AgGridVue } from 'ag-grid-vue'
import CellRender from '../AgGrid/CellRender.vue'
import CustomHeader from '../AgGrid/CustomHeader'
import DateFloatingFilter from '../AgGrid/DateFloatingFilter'
import AutoFilterSelectEditor from '../AgGrid/AutoFilterSelectEditor'
import DateEditor from '../AgGrid/DateEditor'
import EditRenderer from '../AgGrid/EditRenderer'
import InputEditor from '../AgGrid/InputEditor'
import SelectEditor from '../AgGrid/SelectEditor'
import SwitchEditor from '../AgGrid/SwitchEditor'
import gridDefaultColumns from '@/assets/js/gridDefaultColumns'
import ActionRender from '../AgGrid/ActionRender'
import TableFilter from '../AgGrid/TableFilter.vue'
import * as XLSX from 'xlsx/xlsx.mjs'
import bus from '@/bus/bus'

//excel单次导入数量
export const excelImportSize = 100

export default {
  name: 'BaseTable',
  props: {
    dateKey: {
      type: String,
      default: ''
    },
    //表格数据传入
    data: {
      type: Array,
      default: () => []
    },
    //表格数据请求地址ueryAllReceiptList
    api: {
      type: String
    },
    //表格数据请求参数
    apiParams: {
      type: Object,
      default: () => {}
    },
    //表格数据请求方式post/get
    apiMethod: {
      type: String,
      default: 'post'
    },
    //进入页面立刻请求数据
    immediate: {
      type: Boolean,
      default: true
    },
    //列表返回参数配置项
    cbFun: {
      type: Function
    },
    //表格设置按键可见
    tableSettingVisible: {
      type: Boolean,
      default: false
    },
    //配置列表参数menu_list_code：列表code，menu_code：菜单code
    columnConfig: {
      type: Object,
      default: () => {}
    },
    //默认表格列配置
    defaultColDef: {
      type: Object,
      default: function() {
        return {}
      }
    },
    //传入表格列
    columnSource: {
      type: Array,
      default: function() {
        return []
      }
    },
    //额外数据列
    extraColumns: {
      type: Array,
      default: function() {
        return []
      }
    },
    //行的 className 的回调方法
    rowClassName: {
      type: Function,
      default: null
    },
    //单元格的 className 的回调方法
    cellClassName: {
      type: Function,
      default: null
    },
    //当前行是否高亮
    highlightCurrentRow: {
      type: Boolean,
      default: false
    },
    //是否显示复选框
    hasCheck: {
      type: Boolean,
      default: false
    },
    //是否显示序号
    // hasIndex: {
    //   type: Boolean,
    //   default: false,
    // },
    //是否显示编辑图标
    hasEdit: {
      type: Boolean,
      default: false
    },
    //拖拽图标时是否默认拖动行
    rowDragManaged: {
      type: Boolean,
      default: false
    },
    //是否显示删除条件查询和条件查询按钮
    searchBox: {
      type: Boolean,
      default: true
    },
    //是否在表尾显示合计行
    showSummary: {
      type: Boolean,
      default: false
    },
    //是否显示筛选行
    tmsShowFilter: {
      type: Boolean,
      default: true
    },
    //排序
    // sortable: {
    //   type: Boolean,
    //   default: false,
    // },
    //是否为远程搜索
    remoteFilter: {
      type: Boolean,
      default: true
    },
    // summary合计行位置
    summaryPosition: {
      type: String,
      default: 'bottom'
    },
    //自定义的合计计算方法(tms-table)
    summaryMethod: {
      type: Function,
      default: null
    },
    //自定义的合计计算方法(ag-grid)
    summaryMethodAgGrid: {
      type: Function,
      default: null
    },
    //行单击事件
    rowClick: {
      type: Function,
      default: function() {}
    },
    //行双击事件
    rowdblClick: {
      type: Function,
      default: function() {}
    },
    //行拖拽事件
    rowDragEnd: {
      type: Function,
      default: function() {}
    },
    //其他高度
    otherHeight: {
      type: Number,
      default: 0
    },
    //是否分页
    pageDetail: {
      type: Boolean,
      default: true
    },
    pagination: {
      type: Boolean,
      default: true
    }
    // //表格数据总条数
    // total: {
    //     type: Number,
    //     default: 0,
    // },
    // //当前页数
    // page: {
    //     type: Number,
    //     default: 1,
    // },
    // //每页显示几条数据
    // pageSize: {
    //     type: Number,
    //     default: function () {
    //         return this.PAGESIZE;
    //     },
    // },
    // pageSizes: {
    //     type: Array,
    //     default: function () {
    //         return this.PAGESIZES;
    //     },
    // },
  },
  data() {
    return {
      filterParams: {},
      loading: false,
      tableLoading: false,
      showTableSetting: false,
      gridObj: null,
      gridOptions: {
        getRowClass: this.rowClass,
        enableCellTextSelection: true,
        defaultColDef: {
          lockPosition: true
        }
      },
      localeText: {
        noRowsToShow: this.$t('other.none')
      },
      hasIndex: true,
      rowSelection: 'multiple',
      resizedColsMap: {},
      curSumObj: {}, //当前页合计行
      curTotal: 0, //当前页行数
      columns: [], //表格最终显示的列
      allColumns: [], //系统默认配置的列
      showColumns: [], //用户自定义表格配置的列
      hideColumns: [],
      leftMultipleSelection: [], //表格配置左侧表格选中数据
      rightMultipleSelection: [], //表格配置右侧表格选中数据
      defaultSettingObj: {}, //系统默认模块表格配置对象
      userSettingObj: {}, //用户自定义模块表格配置对象
      settingTab: 'first',
      //导出配置
      showExportColumns: [], //用户自定义导出配置的列
      hideExportColumns: [],
      leftExportMultipleSelection: [], //导出配置左侧表格选中数据
      rightExportMultipleSelection: [], //导出配置右侧表格选中数据
      defaultExportSettingObj: {}, //系统默认模块导出配置对象
      userExportSettingObj: {}, //用户自定义模块导出配置对象
      rowData: [],
      pageNum: 1,
      pageSize: 20,
      total: 0,
      pageSizes: this.pageSizes,
      tableSetLoading: false,
      listConfig: {},
      options: {}
    }
  },
  computed: {
    isGroup() {
      return this.columns.some(obj => !this.isResultEmpty(obj.children))
    },
    tableHeight() {
      let height = this.calcHeight(0)
      if (this.otherHeight !== 0) {
        height = this.calcHeight(this.otherHeight)
      }
      if (this.pageDetail) {
        height = height - 60
      }
      return height
    },
    pinnedWidth() {
      const { hasCheck, hasIndex, hasEdit } = this
      let width = 30
      if (hasCheck && !hasEdit) {
        width = 60
      }
      if (!hasCheck && !hasEdit) {
        width = 60
      }
      return width
    }
  },
  components: {
    AgGridVue,
    CellRender,
    CustomHeader,
    ActionRender,
    DateFloatingFilter,
    AutoFilterSelectEditor,
    DateEditor,
    EditRenderer,
    InputEditor,
    SelectEditor,
    SwitchEditor,
    TableFilter
  },
  created() {
    this.initSetting()
  },
  beforeMount() {
    this.gridOptions.context = {
      componentParent: this
    }
    if (this.immediate) {
      this.getTableData()
    }
  },
  methods: {
    getTableData() {
      const { api, apiParams, apiMethod } = this
      if (api) {
        const { pageNum, pageSize, listConfig } = this
        let params = { pageNum, pageSize, ...apiParams, ...listConfig }
        const filterParams = this._.cloneDeep(this.filterParams)
        if (!this._.isEmpty(filterParams)) {
          Object.keys(filterParams).forEach(key => {
            // const field = this.columns.find(col => col.code == key)
            // if (['5'].includes(field.issearch)) {
            //   if (
            //     Array.isArray(filterParams[key]) &&
            //     filterParams[key].length == 2
            //   ) {
            //     params[key + 'Begin'] = filterParams[key][0]
            //     params[key + 'End'] = filterParams[key][1]
            //   } else {
            //     delete params[key + 'Begin']
            //     delete params[key + 'End']
            //   }
            //   delete params[key]
            // } else if (field.issearch == 3) {
            //   params[key + 'str'] = filterParams[key]
            //   delete params[key]
            // } else {
            //   params[key] = filterParams[key]
            // }
            params[key] = filterParams[key]
          })
        }
        this.loading = true
        Object.keys(params).forEach(key => {
          if (params[key] == null || params[key] == '') {
            delete params[key]
          }
        })
        const apiUrl = api
          .replace('{page}', pageNum)
          .replace('{size}', pageSize)
        this.$api[apiMethod](apiUrl, params)
          .then(res => {
            let returnData = { list: [], pageNum: 1, pageSize: 20, total: 0 }
            if (this.cbFun && typeof this.cbFun == 'function') {
              returnData = this.cbFun(res)
            } else {
              const data = res.data || res.page || res.bean
              returnData.list = data?.list || data?.records || []
              // returnData.pageNum = data.curPage
              // returnData.pageSize = data.pageSize
              returnData.total = data?.total || 0
              if (this.showSummary) {
                this.summaryInit(data.totalData)
              }
            }
            this.rowData = returnData.list
            if (this.pageDetail) {
              // this.pageNum = returnData.pageNum;
              // this.pageSize = returnData.pageSize;
              this.total = returnData.total
            }
          })
          .finally(() => {
            this.loading = false
          })
      } else {
        if (Array.isArray(this.data) && this.data.length > 0) {
          this.rowData = this.data
        }
      }
    },
    summaryInit(totalData) {
      const summaryData = [
        { index: this.$t('model.total'), summary: true, ...totalData }
      ]
      this.gridObj.api.setPinnedBottomRowData(summaryData)
    },
    //初始化设置
    initSetting() {
      this.columns = []
      if (this.columnSource && this.columnSource.length > 0) {
        this.columns = this.columnSource.map(obj => this.elTableToAgGrid(obj))
        this.afterInitColumn()
        this.showColumns = this.columns
        this.allColumns = this.columns
        this.showExportColumns = this.columns
      } else {
        this.tableLoading = true
        const { menu_list_code, menu_id } = this.columnConfig
        if (
          menu_list_code === 'gridColumnsInfo' &&
          menu_id === 'gridColumnsInfo'
        ) {
          this.columns = this.columns.concat(gridDefaultColumns.info)
          this.afterInitColumn()
          return
        }
        if (
          menu_list_code === 'gridColumnsSort' &&
          menu_id === 'gridColumnsSort'
        ) {
          this.columns = this.columns.concat(gridDefaultColumns.sort)
          this.afterInitColumn()
          return
        }
        if (
          menu_list_code === 'tableConfigList' &&
          menu_id === 'tableConfigList'
        ) {
          this.columns = this.columns.concat(gridDefaultColumns.tableConfigList)
          this.afterInitColumn()
          return
        }
        this.getColumnConfig()
      }
    },
    //获取表格配置项
    getColumnConfig() {
      getColumnConfig(this.columnConfig)
        .then(res => {
          this.hideColumns = res.data.tableHiding || []
          this.showColumns = res.data.tableDisplay || []
          this.hideExportColumns = res.data.exportHidden || []
          this.showExportColumns = res.data.exportDisplay || []
          const { configureSorting, totalSqlText } = res.data
          this.listConfig = { configureSorting, totalSqlText }
          let arr = res.data.tableDisplay || []
          arr.concat(this.extraColumns)
          this.columns = arr.map(item => this.elTableToAgGrid(item))
          this.afterInitColumn()
          this.allColumns = this.columns
          this.gridObj.api.setColumnDefs(this.columns)
          this.$nextTick(() => {
            this.tableLoading = false
          })
        })
        .catch(() => {
          this.tableLoading = false
        })
    },
    afterInitColumn() {
      const columns = this._.cloneDeep(this.columns)
      let pl_width = 0
      columns[0].pinned = 'left'
      columns[0].maxWidth = columns[0].width
      pl_width += columns[0].width
      this.columns = columns
      let prependColumns = []
      if (this.hasIndex) {
        //序号列
        let _self = this
        let indexCloumn = {
          headerName: this.$t('app.index'),
          field: 'index',
          maxWidth: 46,
          minWidth: 46,
          width: 46,
          pinned: 'left',
          cellStyle: { 'text-align': 'center' },
          cellRenderer: _self.indexFormat,
          headerClass: 'tms-no-children-header'
        }
        pl_width += 46
        prependColumns.push(indexCloumn)
      }
      if (this.hasCheck) {
        //选择列
        let checkCloumn = {
          headerName: '',
          field: 'selection',
          checkboxSelection: true,
          headerCheckboxSelection: true,
          headerCheckboxSelectionFilteredOnly: true,
          maxWidth: this.pinnedWidth,
          minWidth: this.pinnedWidth,
          width: this.pinnedWidth,
          pinned: 'left',
          cellClass: 'tms-cell-index-select',
          headerClass: 'tms-no-children-header'
        }
        pl_width += this.pinnedWidth
        prependColumns.push(checkCloumn)
      }
      if (this.hasEdit) {
        //编辑列
        let checkCloumn = {
          headerName: '',
          field: 'edit',
          maxWidth: this.pinnedWidth,
          minWidth: this.pinnedWidth,
          width: this.pinnedWidth,
          pinned: 'left',
          cellClass: params => {
            if (params.data.summary) {
              return
            } else {
              return 'el-icon-edit'
            }
          },
          headerClass: 'tms-no-children-header'
        }
        pl_width += this.pinnedWidth
        prependColumns.push(checkCloumn)
      }
      this.columns = prependColumns.concat(this.columns)
      this.$nextTick(() => {
        const scrollDom = this.$refs.agGridVue.$el.querySelector(
          '.ag-body-horizontal-scroll-viewport'
        )
        scrollDom.style.paddingLeft = pl_width + 'px'
      })
    },
    /**
     * el-table列配置项转换为ag-grid列配置项
     * 参数：elColumn：el-table的列配置
     * 返回：ag-grid的列配置
     */
    elTableToAgGrid(elColumn) {
      let agColumn = this._.cloneDeep(elColumn)
      agColumn.resizable = false
      // agColumn.sortable = this.sortable;
      agColumn.floatingFilter = this.tmsShowFilter
      agColumn.headerName = elColumn.name || elColumn.label || ''
      agColumn.field = elColumn.code || elColumn.prop
      if (elColumn.width) {
        agColumn.width = parseInt(elColumn.width)
        agColumn.minWidth = parseInt(elColumn.width)
        agColumn.maxWidth = parseInt(elColumn.width)
      } else {
        agColumn.width = 100
        agColumn.minWidth = 100
      }
      if(agColumn.prop == 'action'){
        agColumn.cellRenderer = "CellRender"
      }
      if (elColumn.input) {
        agColumn.filter = 'agTextColumnFilter'
        agColumn.floatingFilterComponent = 'TableFilter'
        agColumn.floatingFilterComponentParams = {
          props: elColumn
        }
        if (['select', 'selects'].includes(agColumn.input)) {
          if (Array.isArray(agColumn.options)) {
            agColumn.cellRenderer = params => {
              return (
                agColumn.options.find(opt => opt.value == params.value)
                  ?.label || params.value
              )
            }
            bus.$emit('filterParamChange', agColumn)
          } else {
            this.getOptions(agColumn)
          }
        }
      }
      if(!this.tmsShowFilter&&agColumn.field == 'action'){
        agColumn.headerComponent = "CustomHeader"
      }
      if (agColumn.type == 'number') {
        agColumn.cellStyle = { 'text-align': 'right' }
      }
      if (agColumn.field == 'index' || agColumn.field == 'selection') {
        agColumn.cellClass = 'tms-cell-index-select'
      } else {
        agColumn.cellClass = this.cellClass
      }
      return agColumn
    },
    //获取表格下拉数据
    getOptions(column) {
      let searchData = column.optionsApi
      if (searchData) {
        this.$get(searchData).then(res => {
          const options = Array.isArray(res) ? res : res.data
          for (let i = 0; i < this.columns.length; i++) {
            const colDef = this.columns[i]
            if (colDef.code == column.code) {
              colDef.cellRenderer = params => {
                return (
                  options.find(opt => opt.code == params.value)?.description ||
                  params.value
                )
              }
              colDef.options = options
              bus.$emit('filterParamChange', colDef)
              break
            }
          }
          this.gridObj.api.setColumnDefs(this.columns)
        })
      } else {
        const name = column.name
        console.log(`列表${name}字段查询数据配置有误2`)
      }
    },
    actionEvent(action, data) {
      this.$emit(action, data)
    },
    /**
     * ag-grid列配置项转换为el-table列配置项
     * 参数：ag-grid的列配置
     * 返回：elColumn：el-table的列配置
     */
    agGridToElTable(agColumn) {
      let elColumn = this._.cloneDeep(agColumn)
      if (elColumn.field === 'index' || elColumn.field === 'selection') {
        elColumn.type = elColumn.field
      }
      elColumn.property = elColumn.field
      elColumn.label = elColumn.headerName
      if (elColumn.filter == 'agDateColumnFilter') {
        elColumn.tmsFilterType = 'date'
      } else if (elColumn.filter == 'agNumberColumnFilter') {
        elColumn.tmsFilterType = 'number'
      } else {
        elColumn.tmsFilterType = 'string'
      }
      if (elColumn.children && !this.isResultEmpty(elColumn.children)) {
        elColumn.children = elColumn.children.map(obj => {
          return this.agGridToElTable(obj)
        })
      }
      return elColumn
    },
    /*
     * 表格配置数据格式化
     * 参数：defaultSetting——系统默认配置
     *       userSetting——用户自定义配置
     *       extraColumn——需要进行额外配置的列
     * 返回：{
     *          allColumns——默认列
     *          userColumns——用户自定义列
     *       }
     */
    tableHeadSetting(defaultSetting, userSetting, extraColumn) {
      //默认所有列配置格式化
      let allColumns = JSON.parse(defaultSetting.dataListConfig)
      allColumns = allColumns.map((obj, index) => {
        if (obj.children && !this.isResultEmpty(obj.children)) {
          obj.children = obj.children.map(child => {
            let childExtra = extraColumn.filter(childCol => {
              return childCol.prop == child.prop
            })
            child = Object.assign(child, childExtra[0])
            return child
          })
        }
        let extra = extraColumn.filter(col => {
          return col.prop == obj.prop
        })
        obj = Object.assign(obj, extra[0])
        return obj
      })
      //用户自定义列配置格式化
      let userColumns = JSON.parse(userSetting.dataListConfig)
      userColumns = userColumns.map((obj, index) => {
        if (obj.children && !this.isResultEmpty(obj.children)) {
          obj.children = obj.children.map(child => {
            let childExtra = extraColumn.filter(childCol => {
              return childCol.prop == child.prop
            })
            child = Object.assign(child, childExtra[0])
            return child
          })
        }
        let extra = extraColumn.filter(col => {
          return col.prop == obj.prop
        })
        obj = Object.assign(obj, extra[0])
        obj = this.elTableToAgGrid(obj)
        return obj
      })
      return {
        allColumns: allColumns,
        userColumns: userColumns
      }
    },
    rowClass(params) {
      let obj = {
        row: params.data,
        rowIndex: params.rowIndex
      }
      if (typeof this.rowClassName === 'string') {
        return this.rowClassName
      } else if (typeof this.rowClassName === 'function') {
        if (params.data.tmsSummary) {
          return ''
        } else {
          return this.rowClassName.call(null, obj)
        }
      } else {
        return ''
      }
    },
    //每页条数change
    handleSizeChange(size) {
      this.pageSize = size
      this.pageNum = 1
      this.getTableData()
      this.$emit('size-change', size)
    },
    //当前页数change
    handleCurrentChange(currentPage) {
      this.pageNum = currentPage
      this.getTableData()
      this.$emit('current-change', currentPage)
    },
    //当用户手动勾选数据行的 Checkbox 时触发的事件
    select(event) {
      let selection = event.api.getSelectedRows()
      this.$emit('select', selection, event.data)
      if (!this.hasCheck) {
        this.currentChange(event)
      }
    },
    //当选择项发生变化时会触发该事件
    selectionChange(event) {
      let selection = event.api.getSelectedRows()
      this.$emit('selection-change', selection)
    },
    //用于多选表格，清空用户的选择
    clearSelection() {
      this.gridObj.api && this.gridObj.api.deselectAll()
    },
    //切换某一行的选中状态
    toggleRowSelection(row, selected) {
      let _self = this
      this.gridObj.api.forEachNode(function(node) {
        if (_self.isObjEqual(node.data, row)) {
          node.setSelected(selected)
        }
      })
    },
    // 用于单选表格，设定某一行为选中行，如果调用时不加参数，则会取消目前高亮行的选中状态
    setCurrentRow(row) {
      this.clearSelection()
      let _self = this
      if (!_self.hasCheck) {
        _self.gridObj.api.forEachNode(function(node) {
          if (_self.isObjEqual(node.data, row)) {
            node.setSelected(true)
          }
        })
      }
    },
    //当表格的当前行发生变化的时候会触发该事件
    currentChange(event) {
      this.$emit('table-current-change', event.data, {})
    },
    //index序号格式化
    indexFormat(params) {
      if (params.data.summary) {
        return params.value
      } else {
        if (this.pageDetail) {
          return (this.pageNum - 1) * this.pageSize + (params.rowIndex + 1)
        } else {
          return params.rowIndex + 1
        }
      }
    },
    onGridReady(params) {
      this.gridObj = params
      this.$emit('grid-ready', params)
    },
    tmsColumnsFit(params) {
      if (params.type === 'gridSizeChanged' && params.clientWidth === 0) {
        return
      }
      this.gridObj = params
      params.api.sizeColumnsToFit()
    },
    onCellClicked(event) {
      if (
        event.colDef.editable === true ||
        this.defaultColDef.editable === true
      ) {
        return
      }
      if (event.colDef.field == 'edit') {
        // 这里一定是点击的编辑
        this.$emit('setdialog', event.data)
        return
      }
      // 非空则复制到粘贴板
      if (event.event.target.innerText !== '') {
        this.$copyText(event.event.target.innerText)
      }
      this.$emit('cellClick', event)
    },
    onCellDoubleClicked(event) {
      this.$emit('cell-dblclick', event)
    },
    onRowClicked(event) {
      this.rowClick(event.data)
    },
    onRowDoubleClicked(event) {
      this.rowdblClick(event.data)
    },
    onCellEditingStopped(event) {
      let updateData = this._.cloneDeep(this.data)
      if (
        event.colDef.cellEditor == 'agSelectCellEditor' &&
        Array.isArray(event.colDef.options)
      ) {
        updateData[event.rowIndex][
          event.colDef.field
        ] = event.colDef.options.find(opt => opt.label == event.value).value
        this.$emit('update:data', updateData)
      }
    },
    onRowDragEnd(event) {
      var itemsToUpdate = []
      event.api.forEachNodeAfterFilterAndSort(function(rowNode) {
        itemsToUpdate.push(rowNode.data)
      })
      this.$emit('update:data', itemsToUpdate)
      this.$emit('row-drag-end', itemsToUpdate)
    },
    onRowEditingStopped(event) {
      console.log(event)
    },
    sortChangeHandler(event) {
      event.api.refreshCells({ force: true })
      this.$emit('sort-changed', event)
    },
    filterChangeHandler(filter) {
      this.pageNum = 1
      this.queryDateList = []
      // if(this.dateKey == filter.key){
      //   this.queryDateList = [];
      // }
      this.filterParams[filter.key] = filter.filter
      this.getTableData()
    },
    /**
     * 日期筛选框comparator
     */
    filterComparator(filterLocalDateAtMidnight, cellValue) {
      let dateAsString = this.formatDateGlobal(cellValue, 'yyyy-MM-dd')
      if (dateAsString == null) return -1
      let dateParts = dateAsString.split('-')
      let cellDate = new Date(
        Number(dateParts[0]),
        Number(dateParts[1]) - 1,
        Number(dateParts[2])
      )
      if (filterLocalDateAtMidnight.getTime() === cellDate.getTime()) {
        return 0
      }
      if (cellDate.getTime() < filterLocalDateAtMidnight.getTime()) {
        return -1
      }
      if (cellDate.getTime() > filterLocalDateAtMidnight.getTime()) {
        return 1
      }
    },
    //设置
    tableSetting() {
      this.showTableSetting = true
    },
    leftSelectionChange(selections) {
      this.leftMultipleSelection = selections
    },
    rightSelectionChange(selections) {
      this.rightMultipleSelection = selections
    },
    //拖拽初始化
    setSort() {
      //表格配置拖拽
      const el = document.querySelectorAll(
        '.right-table-setting .el-table__body-wrapper > table > tbody'
      )[0]
      let _self = this
      this.sortable = Sortable.create(el, {
        ghostClass: 'sortable-ghost',
        handle: '.el-icon-rank',
        onEnd: evt => {
          const targetRow = _self.showColumns.splice(evt.oldIndex, 1)[0]
          _self.showColumns.splice(evt.newIndex, 0, targetRow)
        }
      })
      //导出配置拖拽
      const exportEl = document.querySelectorAll(
        '.right-export-table .el-table__body-wrapper > table > tbody'
      )[0]
      this.sortExportable = Sortable.create(exportEl, {
        ghostClass: 'sortable-ghost',
        onEnd: evt => {
          const targetExportRow = _self.showExportColumns.splice(
            evt.oldIndex,
            1
          )[0]
          _self.showExportColumns.splice(evt.newIndex, 0, targetExportRow)
        }
      })
    },
    //右移
    moveRight() {
      if (this.leftMultipleSelection.length > 0) {
        this.leftMultipleSelection.forEach(item => {
          const index = this.hideColumns.findIndex(col => col.code == item.code)
          this.hideColumns.splice(index, 1)
        })
      }
      this.showColumns = this.showColumns.concat(this.leftMultipleSelection)
    },
    //左移
    moveLeft() {
      if (this.rightMultipleSelection.length > 0) {
        this.rightMultipleSelection.forEach(item => {
          const index = this.showColumns.findIndex(col => col.code == item.code)
          this.showColumns.splice(index, 1)
        })
      }
      this.hideColumns = this.hideColumns.concat(this.rightMultipleSelection)
    },
    /*
     *导出设置
     */
    leftExportSelectionChange(selections) {
      this.leftExportMultipleSelection = selections
    },
    rightExportSelectionChange(selections) {
      this.rightExportMultipleSelection = selections
    },
    //右移
    moveExportRight() {
      if (this.leftExportMultipleSelection.length > 0) {
        this.leftExportMultipleSelection.forEach(item => {
          const index = this.hideExportColumns.findIndex(
            col => col.code == item.code
          )
          this.hideExportColumns.splice(index, 1)
        })
      }
      this.showExportColumns = this.showExportColumns.concat(
        this.leftExportMultipleSelection
      )
    },
    //左移
    moveExportLeft() {
      if (this.rightExportMultipleSelection.length > 0) {
        this.rightExportMultipleSelection.forEach(item => {
          const index = this.showExportColumns.findIndex(
            col => col.code == item.code
          )
          this.showExportColumns.splice(index, 1)
        })
      }
      this.hideExportColumns = this.hideExportColumns.concat(
        this.rightExportMultipleSelection
      )
    },
    //应用
    applySetting() {
      const { menu_list_code, menu_code } = this.columnConfig
      let submitData = { menu_code, menu_list_code }
      this.tableSetLoading = true
      if (this.settingTab == 'first') {
        //表格配置
        const columns = this.showColumns.map(col => {
          const {
            code,
            issearch,
            name,
            sort_num,
            type,
            width,
            searchData
          } = col
          return {
            code,
            issearch,
            name,
            sort_num,
            type,
            searchData,
            width: String(width)
          }
        })
        submitData.data_list_config = JSON.stringify(columns)
        submitData.column_config_type = '10002'
        this.$post('/saveDisplayedOrExportedColumns', submitData)
          .then(res => {
            this.$message.success(this.$t('msg.msg45'))
            this.showTableSetting = false
            this.getColumnConfig()
          })
          .finally(() => {
            this.tableSetLoading = false
          })
      } else if (this.settingTab == 'second') {
        //导出配置
        const columns = this.showExportColumns.map(col => {
          const {
            code,
            issearch,
            name,
            sort_num,
            type,
            width,
            searchData
          } = col
          return {
            code,
            issearch,
            name,
            sort_num,
            type,
            searchData,
            width: String(width)
          }
        })
        submitData.data_list_config = JSON.stringify(columns)
        submitData.column_config_type = '10003'
        this.$post('/saveDisplayedOrExportedColumns', submitData)
          .then(res => {
            this.$message.success(this.$t('msg.msg46'))
            this.showTableSetting = false
            this.getColumnConfig()
          })
          .finally(() => {
            this.tableSetLoading = false
          })
      }
    },
    //恢复默认
    resetSetting() {
      const { menu_list_code, menu_code } = this.columnConfig
      let submitData = { menu_code, menu_list_code }
      if (this.settingTab == 'first') {
        //表格配置
        submitData.column_config_type = '10002'
        this.$post('/reDefaultConfig', submitData)
          .then(res => {
            this.$message.success(this.$t('msg.msg47'))
            this.showTableSetting = false
            this.getColumnConfig()
          })
          .finally(() => {
            this.tableSetLoading = false
          })
      } else if (this.settingTab == 'second') {
        //导出配置
        submitData.column_config_type = '10003'
        this.$post('/reDefaultConfig', submitData)
          .then(res => {
            this.$message.success(this.$t('msg.msg48'))
            this.showTableSetting = false
            this.getColumnConfig()
          })
          .finally(() => {
            this.tableSetLoading = false
          })
      }
    },
    //删除查询条件
    delSearchData() {
      // this.gridObj.api.setFilterModel(null);
      bus.$emit('resetFliterParams')
      this.pageNum = 1
      this.filterParams = {}
      this.getTableData()
    },
    delSelectData(params) {
      console.log(params)
    },
    readFile(file) {
      //文件读取
      return new Promise(resolve => {
        let reader = new FileReader()
        reader.readAsBinaryString(file) //以二进制的方式读取
        reader.onload = ev => {
          resolve(ev.target.result)
        }
      })
    },
    // 解析excel
    async excelParsing(file, range) {
      let data = await this.readFile(file)
      // 解析二进制格式数据 -- cellDates: true 处理时间格式
      let workbook = XLSX.read(data, { type: 'binary', cellDates: true })
      //  获取第一个Sheet
      let worksheet = workbook.Sheets[workbook.SheetNames[0]]
      // 读取文件内容，（第一个sheet里的内容）
      // range：设置从第几行开始读取内容 ; defval 为空时显示列值为空
      // json数据格式
      let result = XLSX.utils.sheet_to_json(worksheet, {
        range: range,
        defval: ''
      })
      // 最终解析的 json 格式数据:'
      return result
    },
    // 解析excel多个sheet
    async excelManySheetParsing(file, range) {
      let data = await this.readFile(file)
      // 解析二进制格式数据
      let workbook = XLSX.read(data, { type: 'binary' })

      const obj = {}
      let size = 'Size'
      let opts = { range: range, defval: '' }
      let sheetSize = workbook.SheetNames.length
      if (sheetSize > 1) {
        obj.isSubSheet = true
        obj.subSheetSize = sheetSize - 1
      }
      // 遍历多个sheet工作区
      workbook.SheetNames.forEach((item, index) => {
        if (index === 0) {
          // json数据格式
          obj.masterSheet = XLSX.utils.sheet_to_json(
            workbook.Sheets[item],
            opts
          )
          obj.masterSize = obj.masterSheet.length
        } else {
          let subName = 'subSheet' + index
          obj[subName] = XLSX.utils.sheet_to_json(workbook.Sheets[item], opts)
          obj[subName + size] = obj[subName].length
        }
      })
      return obj
    },
    uuid(len, radix) {
      var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(
        ''
      )
      var uuid = [],
        i
      radix = radix || chars.length

      if (len) {
        // Compact form
        for (i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)]
      } else {
        // rfc4122, version 4 form
        var r

        // rfc4122 requires these characters
        uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
        uuid[14] = '4'

        // Fill in random data.  At i==19 set the high bits of clock sequence as
        // per rfc4122, sec. 4.1.5
        for (i = 0; i < 36; i++) {
          if (!uuid[i]) {
            r = 0 | (Math.random() * 16)
            uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r]
          }
        }
      }
      return uuid.join('')
    }
  },
  watch: {
    showTableSetting(val) {
      if (val) {
        this.$nextTick(() => {
          this.setSort()
        })
      } else {
        this.getColumnConfig()
      }
    },
    columnSource(val) {
      this.$emit('update:columnSource', val)
      this.initSetting()
    },
    extraColumns(val) {
      this.$emit('update:extraColumns', val)
      this.initSetting()
    },
    columns(val) {
      this.$emit('update:columns', val)
      this.showColumns = Object.assign([], val).filter(obj => {
        return (
          obj.field !== 'index' &&
          obj.field !== 'selection' &&
          obj.field !== 'edit'
        )
      })
    },
    data(val) {
      this.getTableData()
    },
    otherHeight: {
      handler(val) {
        // this.$emit("update:height", val);
        // this.gridObj.api && this.gridObj.api.doLayout();
      },
      immediate: true
    },
    hasCheck(val) {
      if (!val) {
        this.rowSelection = 'single'
      }
    },
    apiParams: {
      handler(data) {
        this.getTableData()
      },
      deep: true
    }
  }
}
</script>
<style lang="scss" scoped>
  .query-date-wrap {
    position: absolute;
    right: 0;
    top: -26px;
    span {
      display: inline-block;
      margin-right: 0;
      text-align: right;
      font-size: 14px;
    }
    .el-checkbox-group {
      display: inline-block;
    }
  }
  .tms-ag-grid {
    position: relative;

    &.no-edit.no-check {
    }

    .table-setting {
      position: absolute;
      top: 16px;
      z-index: 100;
      .el-icon-setting {
        font-size: 18px;
      }
    }

    .search_btn {
      position: absolute;
      top: 45px;
      z-index: 100;
      width: 42px;
      display: flex;
      justify-content: space-between;
      i {
        font-size: 18px;
      }
    }
  }
</style>
